home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / sgml / unix / sgmlc / modsgml2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-03  |  18.3 KB  |  445 lines

  1. /******************************************************************************/
  2. /* Added exiterr() for terminal errors to prevent SGML.MSG errors.            */
  3. /******************************************************************************/
  4. #include "sgmlincl.h"         /* #INCLUDE statements for SGML parser. */
  5. /******************************************************************************/
  6. /* ENTDEF: Process an entity definition and return the pointer to it.
  7.            The entity text must be in permanent storage.
  8.            There is no checking to see if the entity already exists;
  9.            the caller must have done that.
  10. */
  11. PECB entdef(
  12. UNCH *ename,                  /* Entity name (with length and EOS). */
  13. UNCH estore,                  /* Entity storage class. */
  14. union etext *petx)            /* Ptr to entity text union. */
  15. {
  16.      PECB p;
  17.  
  18.      p = (PECB)hin((THASH)etab, ename, hash(ename, ENTHASH), ENTSZ);
  19.      memcpy((UNIV)&p->etx, (UNIV)petx, ETEXTSZ);
  20.      p->estore = estore;
  21. #ifndef FINAL
  22.      if (etrace) traceecb("ENTDEF", p);
  23. #endif
  24.      return(p);
  25. }
  26. /******************************************************************************/
  27. /* ENTFIND: If an entity exists, return ptr to its ecb.
  28.             Return NULL if it is not defined.
  29. */
  30. PECB entfind(
  31. UNCH *ename)                  /* Entity name (with length and EOS). */
  32. {
  33.      PECB p;
  34.  
  35.      p = (PECB)hfind((THASH)etab, ename, hash(ename, ENTHASH));
  36. #ifndef FINAL
  37.      if (etrace && p) traceecb("ENTFIND", p);
  38. #endif
  39.      return p;
  40. }
  41. /******************************************************************************/
  42. /* ENTREF: Process a general or parameter entity reference.
  43.            If the entity is defined it returns the return code from ENTOPEN.
  44.            It returns ENTUNDEF for undefined parameter entity references
  45.            and for general entity references when defaulting is not allowed.
  46.            Otherwise, it uses the default entity text.
  47. */
  48. int entref(
  49. UNCH *ename)                  /* Entity name (with length and EOS). */
  50. {
  51.      PECB ecb;                /* Entity control block. */
  52.  
  53.      /* Get the entity control block, if the entity has been defined. */
  54.      if ((ecb = (PECB)hfind((THASH)etab, ename, hash(ename, ENTHASH)))==0) {
  55.           if ( ename[1]==lex.d.pero
  56.             || ecbdeflt==0
  57.             || (ecb = usedef(ename))==0 ) {
  58.                sgmlerr(35, (struct parse *)0, ename+1, NULL);
  59.                return(ENTUNDEF);
  60.           }
  61.      }
  62.      return(entopen(ecb));
  63. }
  64. /******************************************************************************/
  65. /* ENTOPEN: Open a newly referenced entity.
  66.             Increment the stack pointer (es) and initialize the new entry.
  67.             Returns ENTSGI if entity is STARTGI, ENTEGI if it is ENDGI,
  68.             ENTDATA if entity is CDATA or SDATA, ENTPI if it is PI,
  69.             0 if normal and all o.k.; <0 if not.
  70. */
  71. int entopen(
  72. struct entity *ecb)           /* Entity control block. */
  73. {
  74.      int i;                   /* Loop counter. */
  75.  
  76.      /* See if we have exceeded the entity nesting level. */
  77.      if (es>=ENTLVL) {
  78.           sgmlerr(34, (struct parse *)0, ecb->ename+1, NULL);
  79.           return(ENTMAX);
  80.      }
  81.      /* If entity is an etd, pi, or data, return it without creating an scb. */
  82.      switch (ecb->estore) {
  83.      case ESS:
  84.           etisw = 0;
  85.           newetd = ecb->etx.e;
  86.           return(ENTSGI);
  87.      case ESE:
  88.           newetd = ecb->etx.e;
  89.           return(ENTEGI);
  90.      case ESN:
  91.           if (NEDCNID(ecb->etx.n)==0)
  92.                sgmlerr(78,(struct parse *)0, NEDCN(ecb->etx.n)+1, ecb->ename+1);
  93.           data = (UNCH *)ecb->etx.n;
  94.           entdatsw = NDECONT;
  95.           return(ENTDATA);
  96.      case ESC:
  97.      case ESX:
  98.           if((datalen = *(ecb->etx.c) - 2)==0) return(0);
  99.           data = ecb->etx.c+1;
  100.           entdatsw = (ecb->estore==ESC) ? CDECONT : SDECONT;
  101.           return(ENTDATA);
  102.      case ESI:
  103.           datalen = *(ecb->etx.c) - 2;
  104.           data = ecb->etx.c+1;
  105.           entpisw = 4;
  106.           return(ENTPI);
  107.      }
  108.      /* If the same entity is already open, send msg and ignore it.
  109.         Level 0 needn't be tested, as its entity name is always *DOC.
  110.      */
  111.      for (i = 0; ++i<=es;) if (scbs[i].ecb.enext==ecb) {
  112.           sgmlerr(36, (struct parse *)0, ecb->ename+1, NULL);
  113.           return(ENTLOOP);
  114.      }
  115.      /* Update SCB if entity trace is wanted in messages or entity is a file.
  116.         (Avoid this at start when es==-1 or memory will be corrupted.)
  117.      */
  118.      if ((sw.swenttr || FILESW) && es>=0) scbset();
  119.  
  120.      /* Stack the new source control block (we know there is room). */
  121.      ++es;                                      /* Increment scbs index. */
  122.      RCNT = CCO = RSCC = 0;                     /* No records or chars yet. */
  123.      memcpy((UNIV)&ECB, (UNIV)ecb, (UNS)ENTSZ); /* Copy the ecb into the scb. */
  124.      ECBPTR = ecb;            /* Save the ecb pointer in scb.ecb.enext. */
  125. #ifndef FINAL
  126.      if (etrace) traceecb("ENTOPEN", ECBPTR);
  127. #endif
  128.  
  129.      /* For memory entities, the read buffer is the entity text
  130.         (after skipping past the length byte).
  131.         The text starts at FBUF, so FPOS should be FBUF-1
  132.         because it is bumped before each character is read.
  133.      */
  134.      if (ECB.estore<ESFM) {FPOS = (FBUF = ECB.etx.c+1)-1; return 0;}
  135.  
  136.      /* For file entities, suspend any open file and do first read. */
  137.      fileopen();                             /* Open new external file. */
  138.      if (io.ipbrc<0) {                       /* If open not successful: */
  139.           FPOS = FBUF-1;                     /* Clean CCNT for OPEN error msg.*/
  140.           error(FILERR, 32, 0, ecb->ename+1, NULL);
  141.           --es;                              /* Pop the stack. */
  142.           return(ENTFILE);
  143.      }
  144.      filepend(es);                           /* Suspend any open file. */
  145.      fileread();                             /* First read of file must be ok.*/
  146.      return 0;
  147. }
  148. /******************************************************************************/
  149. /* ENTGET: Get next record of entity (if there is one).
  150.            Otherwise, close the file (if entity is a file) and
  151.            pop the entity stack.  If nothing else is on the stack,
  152.            return -1 to advise the caller.
  153. */
  154. /*lint +fvr                      Returned value may be ignored. */
  155. int entget(void)
  156. /*lint -fvr                      Restore normal LINT processing. */
  157. {
  158.      RSCC += (int)(CCO=(UNS)(FPOS-FBUF));
  159.                                    /* Characters-in-record (ignore EOB/EOF). */
  160.      tagctr += (int)CCO;           /* Update tag length counter. */
  161.      switch (*FPOS) {
  162.      case EOBCHAR:                 /* End of file buffer: refill it. */
  163.           fileread();                             /* Read the file. */
  164.           if (io.ipbrc>0) return (0);             /* No errors: return. */
  165.      readerr:
  166.           error(FILERR, 31, 0, ENTITY+1, NULL);/* Treat error as EOF. */
  167.      case EOFCHAR:                 /* End of file: close it. */
  168.           fileclos();              /* Call SGMLIO to close file. */
  169.      conterr:
  170.           if (es==0) {             /* Report if it is primary file. */
  171.                FPOS = FBUF-1;      /* Preserve CCNT for omitted end-tags. */
  172.                return (-1);
  173.           }
  174.      case EOS:                /* End of memory entity: pop the stack. */
  175. #ifndef FINAL
  176.           if (etrace) traceecb("ENTPOP", ECBPTR);
  177. #endif
  178.           --es;                                   /* Pop the SCB stack. */
  179.           if (FBUF) return (0);                   /* Return if not PEND file. */
  180.           filecont();                             /* Resume previous file. */
  181.           if (io.ipbrc<0) {                       /* If CONT not successful: */
  182.                error(FILERR, 94, 0, ENTITY+1, NULL);
  183.                goto conterr;
  184.           }
  185.           fileread();                             /* Read the file. */
  186.           if (io.ipbrc<=0) goto readerr;          /* If READ not successful: */
  187.           if (delmscsw && es==0)                  /* End of DTD. */
  188.                {delmscsw = 0; *rbufs = lex.d.msc;}
  189.           return(0);
  190.      }
  191.      return(0);               /* Avoid lint and TurboC warnings. */
  192. }
  193. /******************************************************************************/
  194. /* USEDEF: Use the default value for an entity reference.
  195.            Returns the ECB for the defaulted entity.
  196. */
  197. PECB usedef(
  198. UNCH *ename)                  /* Entity name (with length and EOS). */
  199. {
  200.      union etext etx;         /* Save return from entgen. */
  201.      PECB ecb;                /* Entity control block. */
  202.      PNE pne;                 /* Ptr to NDATA entity control block. */
  203.      UNCH estore;             /* Default entity storage type. */
  204.  
  205.      if ((estore = ecbdeflt->estore)<ESFM) /* Default is an internal string. */
  206.           etx.c = ecbdeflt->etx.c;
  207.      else {
  208.       /* Move entity name into fpi. */
  209.       memcpy(fpidf.fpinm, ename, (fpidf.fpinml = (char)*ename));
  210.       if ((etx.x = entgen(&fpidf))==0) return (PECB)0;
  211.       if (estore==ESN) {
  212.        memcpy((UNIV)(pne=(PNE)rmalloc((UNS)NESZ)),(UNIV)ecbdeflt->etx.n,(UNS)NESZ);
  213.            NEID(pne) = etx.x;
  214.            etx.n = pne;
  215.       }
  216.      }
  217.      if (sw.swrefmsg) sgmlerr(45, (struct parse *)0, ename+1, NULL);
  218.      ++ds.ecbcnt;
  219.      ecb = entdef(ename, estore, &etx);
  220.      if (estore==ESN) NEENAME(pne) = ecb->ename;
  221.      return(ecb);
  222. }
  223. /******************************************************************************/
  224. /* SCBSET: Set source control block to current location in the current entity.
  225.            This routine is called by SGML when it returns to the text
  226.            processor and by ERROR when it reports an error.
  227. */
  228. VOID scbset(void)
  229. {
  230.      CC = *FPOS;
  231.      CCO = (UNS)(FPOS+1-FBUF);
  232.      return;
  233. }
  234. /******************************************************************************/
  235. /* ENTGEN: Call SGMLIO (FILENM) to generate an external id from an fpi.
  236.            SGMLIO returns a ptr in io.ipbn to the xid in its memory.
  237.            The pointer is zero if no valid identifier could be generated.
  238.            ENTGEN returns a universal pointer because SGML does not need to
  239.            look at the returned data; it is just saved to pass on to SGMLIO
  240.            when the file is opened.
  241. */
  242. UNIV entgen(
  243. struct fpi *fpis)             /* FPI structure. */
  244. {
  245.      io.sgmles = es;                         /* Current SCBS level. */
  246.      io.ipbn = (UNIV)fpis;                   /* FPI structure. */
  247.      io.ipbtype = FILENM; sgmlio(&io);       /* Generate fileid. */
  248.      return(io.ipbn);                        /* Get its long ptr from IPB. */
  249. }
  250. /******************************************************************************/
  251. /* FILEOPEN: Call SGMLIO to open an external entity (file).
  252.              The routine sets io.ipbn to the SGMLIO fcb pointer.
  253. */
  254. VOID fileopen(void)           /* Open an external entity's file. */
  255. {
  256.      io.sgmles = es;                         /* SCBS index for this file. */
  257.      io.ipbn = ECB.etx.x;                    /* Ptr to DOS fileid in tp. */
  258.      io.ipbtype = FILEOPEN; sgmlio(&io);     /* Open the file. */
  259.      SCBFCB = io.ipbn;                       /* Save SGMLIO fcb ptr. */
  260. }
  261. /******************************************************************************/
  262. /* FILEREAD: Call SGMLIO to read an open external entity (file).
  263. */
  264. VOID fileread(void)           /* Read the current external entity's file. */
  265. {
  266.      io.sgmles = es;                         /* SCBS index for this file. */
  267.      io.ipbn = SCBFCB;                       /* Ptr to SGMLIO fcb. */
  268.      io.ipbbuf = rbufs;                      /* Starting read position. */
  269.      io.ipbtype = FILEREAD; sgmlio(&io);     /* Read the file. */
  270.      FPOS = (FBUF = io.ipbbuf)-1;            /* Actual read buffer. */
  271. }
  272. /******************************************************************************/
  273. /* FILEPEND: Call SGMLIO to close an open external entity (file) temporarily.
  274. */
  275. VOID filepend(                /* Close the current external entity's file. */
  276. int es)                      /* Local index to scbs. */
  277. {
  278.      while (--es>=0) {             /* Find last external file on stack. */
  279.           if (!FILESW) continue;   /* Not an external file. */
  280.           FBUF = 0;                /* Indicate pending file. */
  281.           RSCC += (int)CCO;        /* Update characters-in-record counter. */
  282.           tagctr += (int)CCO;      /* Update tag length counter. */
  283.           io.sgmles = es;          /* SCBS index for this file. */
  284.           io.ipbn = SCBFCB;        /* Ptr to SGMLIO fcb. */
  285.           io.ipboff = CCO;         /* Chars read in current block. */
  286.           CCO = 0;                 /* So CCNT will be correct. */
  287.           io.ipbtype = FILEPEND;   /* Close the file. */
  288.           sgmlio(&io);             /* Call sgmlio. */
  289.           return;
  290.      }
  291. }
  292. /******************************************************************************/
  293. /* FILECONT: Call SGMLIO to reopen an external entity (file).
  294. */
  295. VOID filecont(void)           /* Open an external entity's file. */
  296. {
  297.      io.sgmles = es;                         /* SCBS index for this file. */
  298.      io.ipbn = SCBFCB;                       /* Ptr to SGMLIO fcb. */
  299.      io.ipbtype = FILECONT; sgmlio(&io);     /* Open the file. */
  300. }
  301. /******************************************************************************/
  302. /* FILECLOS: Call SGMLIO to close an open external entity (file).
  303. */
  304. VOID fileclos(void)           /* Close the current external entity's file. */
  305. {
  306.      io.sgmles = es;                         /* SCBS index for this file. */
  307.      io.ipbn = SCBFCB;                       /* Ptr to SGMLIO fcb. */
  308.      io.ipbtype = FILECLOS; sgmlio(&io);     /* Close the file. */
  309. }
  310. /******************************************************************************/
  311. /* ERROR: Interface to text processor SGML I/O services for error handling.
  312. */
  313. VOID error(
  314. UNS type,                     /* Type of error. */
  315. UNS number,                   /* Error number. */
  316. UNS errsp,                    /* Index to parse or declaration name. */
  317. UNCH *parm1,                  /* Error message parameters. */
  318. UNCH *parm2)                  /* Error message parameters. */
  319. {
  320.      scbset();                /* Update location in source control block. */
  321.      ie.errtype = type;       /* Type of error: DOC FIL MD SYN. */
  322.      ie.sgmles = es;          /* Current level in scb stack. */
  323.      ie.errnum = number;      /* Error number. */
  324.      ie.errsp = errsp;        /* Index to parse or declaration name. */
  325.      ie.eparm[0] = parm1;     /* Parameter 1 ptr. */
  326.      ie.eparm[1] = parm2;     /* Parameter 2 ptr. */
  327.      sgmlmsg(&ie);
  328.      return;
  329. }
  330. /******************************************************************************/
  331. /* PTRSRCH: Find a pointer in a list and return its index.
  332.             Search key must be on list as there is no limit test.
  333.             This routine is internal only -- not for user data.
  334. */
  335. UNIV mdnmtab[MAXDCLS] = {
  336.      syn.k.attlist,
  337.      syn.k.doctype,
  338.      syn.k.element,
  339.      syn.k.entitee,
  340.      syn.k.linktype,
  341.      syn.k.link,
  342.      syn.k.notation,
  343.      syn.k.sgml,
  344.      syn.k.shortref,
  345.      syn.k.uselink,
  346.      syn.k.usemap
  347. };
  348. UNIV pcbtab[MAXPCBS] = {
  349.      (UNIV)&pcbconc,
  350.      (UNIV)&pcbcone,
  351.      (UNIV)&pcbconm,
  352.      (UNIV)&pcbconr,
  353.      (UNIV)&pcbetag,
  354.      (UNIV)&pcbgrcm,
  355.      (UNIV)&pcbgrcs,
  356.      (UNIV)&pcbgrnm,
  357.      (UNIV)&pcbgrnt,
  358.      (UNIV)&pcblitc,
  359.      (UNIV)&pcblitp,
  360.      (UNIV)&pcblitr,
  361.      (UNIV)&pcblitv,
  362.      (UNIV)&pcbmd,
  363.      (UNIV)&pcbmdc,
  364.      (UNIV)&pcbmdi,
  365.      (UNIV)&pcbmds,
  366.      (UNIV)&pcbmsc,
  367.      (UNIV)&pcbmsi,
  368.      (UNIV)&pcbmsrc,
  369.      (UNIV)&pcbpro,
  370.      (UNIV)&pcbref,
  371.      (UNIV)&pcbstag,
  372.      (UNIV)&pcbval
  373. };
  374. UNS ptrsrch(
  375. UNIV ptrtab[],
  376. UNIV ptr)
  377. {
  378.      UNS i;
  379.  
  380.      for (i = 0; ; ++i) {
  381. #ifndef FINAL
  382.           if (dtrace) {
  383.                if (ptrtab==pcbtab)
  384.                     tracemap(((struct parse *)ptr)->pname,
  385.                              ((struct parse *)ptrtab[i])->pname, (int)i);
  386.                else tracemap(ptr, ((STRING)ptrtab[i])+1, (int)i);
  387.           }
  388. #endif
  389.           if (ptrtab[i]==ptr) return(i);
  390.      }
  391.      /*lint -unreachable         There is no implied return at this point. */
  392. }
  393. /******************************************************************************/
  394. /* MDERR: Process errors for markup declarations.
  395.           Prepare the special parameters that only exist for
  396.           markup declaration errors.
  397. */
  398. VOID mderr(
  399. UNS number,                   /* Error number. */
  400. UNCH *parm1,                  /* Additional parameters (or NULL). */
  401. UNCH *parm2)                  /* Additional parameters (or NULL). */
  402. {
  403.      UNS type = MDERR2;       /* Assume no declaration subject. */
  404.  
  405.      ie.parmno = parmno;                        /* Parameter number. */
  406.      if (subdcl) {
  407.           type = MDERR;
  408.           memcpy(ie.subdcl, subdcl, NAMELEN+1);  /* Dcl subject identifier. */
  409.           ie.subdcl[NAMELEN] = EOS;             /* Truncate if lengthy. */
  410.      }
  411.      error(type, number, MAXPCBS+ptrsrch(mdnmtab, mdname), parm1, parm2);
  412. }
  413. /******************************************************************************/
  414. /* SGMLERR: Process errors for SGML parser.
  415. */
  416. VOID sgmlerr(
  417. UNS number,                   /* Error number. */
  418. struct parse *pcb,            /* Current parse control block. */
  419. UNCH *parm1,                  /* Error message parameters. */
  420. UNCH *parm2)                  /* Error message parameters. */
  421. {
  422.      if (!pcb) pcb = prologsw ? propcb : conpcb;
  423.      error(DOCERR, number, ptrsrch(pcbtab, (UNIV)pcb), parm1, parm2);
  424. }
  425. /******************************************************************************/
  426. /* EXITERR: Process terminal errors for SGML parser.
  427. */
  428. VOID exiterr(
  429. UNS number,                   /* Error number. */
  430. struct parse *pcb)            /* Current parse control block. */
  431. {
  432.      if (!pcb) pcb = prologsw ? propcb : conpcb;
  433.      error(EXITERR, number, ptrsrch(pcbtab, (UNIV)pcb), FPOS, NULL);
  434. }
  435. /******************************************************************************/
  436. /* SYNERR: Process syntax errors for SGML parser.
  437. */
  438. VOID synerr(
  439. UNS number,                   /* Error number. */
  440. struct parse *pcb)            /* Current parse control block. */
  441. {
  442.      error(DOCERR, number, ptrsrch(pcbtab, (UNIV)pcb), NULL, NULL);
  443. }
  444. /******************************************************************************/
  445.